home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / win / hooks.zip / HOOKSDLL.C < prev    next >
C/C++ Source or Header  |  1993-03-18  |  26KB  |  828 lines

  1. //---------------------------------------------------------------------------
  2. //  Windows hooks Sample Application - The DLL
  3. //
  4. //  This sample application demonstrates how to use Windows hooks.
  5. //
  6. //  This File contains the source code for the hooksdll
  7. //
  8. //  Author:    Kyle Marsh
  9. //              Windows Developer Technology Group
  10. //              Microsoft Corp.
  11. //
  12. //---------------------------------------------------------------------------
  13.  
  14.  
  15. #include "windows.h"
  16. #include "string.h"
  17. #include "hooks.h"
  18.  
  19. //---------------------------------------------------------------------------
  20. // Function declarations
  21. //---------------------------------------------------------------------------
  22.  
  23. int   FAR PASCAL LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine);
  24. int   FAR PASCAL WEP (int bSystemExit);
  25. int   FAR PASCAL InitHooksDll(HWND hwndMainWindow, int nWinLineHeight);
  26. int   FAR PASCAL PaintHooksDll(HDC hDC );
  27. int   FAR PASCAL InstallFilter (int nHookIndex, int nCode );
  28. void  FAR PASCAL CallWndProcFunc (int nCode, WORD wParam, DWORD lParam );
  29. int   FAR PASCAL CbtFunc (int nCode, WORD wParam, DWORD lParam );
  30. void  FAR PASCAL GetMessageFunc (int nCode, WORD wParam, DWORD lParam );
  31. DWORD FAR PASCAL JournalPlaybackFunc (int nCode, WORD wParam, DWORD lParam );
  32. void  FAR PASCAL JournalRecordFunc (int nCode, WORD wParam, DWORD lParam );
  33. int   FAR PASCAL KeyboardFunc (int nCode, WORD wParam, DWORD lParam );
  34. int   FAR PASCAL MouseFunc (int nCode, WORD wParam, DWORD lParam );
  35. int   FAR PASCAL SysMsgFilterFunc (int nCode, WORD wParam, DWORD lParam );
  36. char  FAR *szMessageString(WORD wID);
  37.  
  38. //---------------------------------------------------------------------------
  39. // Global Variables...
  40. //---------------------------------------------------------------------------
  41.  
  42. HANDLE    hInstance;        // Global instance handle for  DLL
  43. HWND    hwndMain;        // Main hwnd. We will get this from the App
  44. int    InitCalled = 0;     // Has the Init function been called ?
  45. int    nLineHeight;        // Heigth of lines in window
  46. char    szType[64];        // A Place to write temporary strings
  47. int    nRecordedEvents = -1;    // Number or Events Recorded
  48. DWORD    dwStartRecordTime;    // Time JournalRecord Started
  49.  
  50. typedef struct TAGEventNode {
  51.        EVENTMSG         Event;
  52.     struct TAGEventNode FAR *lpNextEvent;
  53. } EventNode;
  54.  
  55. EventNode FAR *lpEventChain  = NULL;  // Head of recorded Event List
  56. EventNode FAR *lpLastEvent   = NULL;  // Tail of recorded Event List
  57. EventNode FAR *lpPlayEvent   = NULL;  // Current Event being played
  58.  
  59. //
  60. //  My Hook States
  61. //
  62. int HookStates[NUMOFHOOKS] = { 0,0,0,0,0,0,0,0,0 } ; // State Table of my hooks
  63.  
  64. //
  65. //  Hook Codes
  66. //
  67. int HookCodes[NUMOFHOOKS] = {
  68.                    WH_CALLWNDPROC,
  69.                    WH_CBT,
  70.                    WH_GETMESSAGE,
  71.                    WH_JOURNALPLAYBACK,
  72.                    WH_JOURNALRECORD,
  73.                    WH_KEYBOARD,
  74.                    WH_MOUSE,
  75.                    WH_MSGFILTER,
  76.                    WH_SYSMSGFILTER
  77.                 };
  78.  
  79. //
  80. // Filter Function Addresses
  81. //
  82. FARPROC lpfnHookProcs[NUMOFHOOKS] = {
  83.                       (FARPROC) CallWndProcFunc,
  84.                       (FARPROC) CbtFunc,
  85.                       (FARPROC) GetMessageFunc,
  86.                       (FARPROC) JournalPlaybackFunc,
  87.                       (FARPROC) JournalRecordFunc,
  88.                       (FARPROC) KeyboardFunc,
  89.                       (FARPROC) MouseFunc,
  90.                       NULL,
  91.                       (FARPROC) SysMsgFilterFunc,
  92.                     };
  93.  
  94. //
  95. // Hook Handles
  96. //
  97. HHOOK hhookHooks[NUMOFHOOKS];
  98.  
  99. //
  100. // Output Lines
  101. //
  102. char szFilterLine[NUMOFHOOKS][128];
  103.  
  104. //---------------------------------------------------------------------------
  105. // LibMain
  106. //---------------------------------------------------------------------------
  107. int FAR PASCAL LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  108. {
  109.     hInstance = hModule;
  110.     return 1;
  111. }
  112.  
  113. #pragma alloc_text(FIXEDSEG, WEP)
  114.  
  115. //---------------------------------------------------------------------------
  116. // WEP
  117. //---------------------------------------------------------------------------
  118. int FAR PASCAL WEP (int bSystemExit)
  119. {
  120.     return(1);
  121. }
  122.  
  123.  
  124.  
  125. //---------------------------------------------------------------------------
  126. // InitHooksDll
  127. //---------------------------------------------------------------------------
  128. int FAR PASCAL InitHooksDll(HWND hwndMainWindow, int nWinLineHeight)
  129. {
  130.     hwndMain = hwndMainWindow;
  131.     nLineHeight = nWinLineHeight;
  132.  
  133.  
  134.     InitCalled = 1;
  135.     return (0);
  136. }
  137.  
  138.  
  139. //---------------------------------------------------------------------------
  140. // PaintHooksDll
  141. //---------------------------------------------------------------------------
  142. int FAR PASCAL PaintHooksDll(HDC hDC )
  143. {
  144.    int i;
  145.  
  146.    for (i = 0; i < NUMOFHOOKS; i++ ) {
  147.        if ( HookCodes[i] != WH_MSGFILTER && HookStates[i] )
  148.        TabbedTextOut(hDC, 1, nLineHeight * i,
  149.         (LPSTR)szFilterLine[i], strlen(szFilterLine[i]), 0, NULL, 1);
  150.    }
  151.  
  152.    return (0);
  153. }
  154.  
  155. //---------------------------------------------------------------------------
  156. // InstallSysMsgFilter
  157. //
  158. // Install / Remove Filter function for the WH_SYSMSGFILTER
  159. //
  160. //---------------------------------------------------------------------------
  161. int FAR PASCAL InstallFilter (int nHookIndex, int nCode )
  162. {
  163.  
  164.      if ( ! InitCalled ) {
  165.     return (-1);
  166.      }
  167.      if ( nCode ) {
  168.     hhookHooks[nHookIndex] =
  169.           SetWindowsHookEx(HookCodes[nHookIndex], (HOOKPROC) lpfnHookProcs[nHookIndex], hInstance,NULL);
  170.     HookStates[nHookIndex] = TRUE;
  171.      }
  172.      else {
  173.     UnhookWindowsHookEx(hhookHooks[nHookIndex]);
  174.     HookStates[nHookIndex] = FALSE;
  175.     InvalidateRect(hwndMain, NULL, TRUE);
  176.     UpdateWindow(hwndMain);
  177.      }
  178. }
  179.  
  180. //---------------------------------------------------------------------------
  181. // CallWndProcFunc
  182. //
  183. // Filter function for the WH_CALLWNDPROC
  184. //
  185. //---------------------------------------------------------------------------
  186. void FAR PASCAL CallWndProcFunc (int nCode, WORD wParam, DWORD lParam )
  187. {
  188.    HDC           hDC;
  189.    // structure used for CallWpnProc
  190.    struct tempStruct
  191.      {
  192.        LONG       lParam;
  193.        WORD       wParam;
  194.        WORD       message;
  195.        HWND       hwnd;
  196.      } FAR * lptsParamStruct;
  197.  
  198.  
  199.    if ( nCode >= 0 ) {
  200.  
  201.       lptsParamStruct = (struct tempStruct FAR *) lParam;
  202.  
  203.       if ( wParam )
  204.      _fstrcpy(szType,"From Current Task");
  205.       else
  206.      _fstrcpy(szType," ");
  207.  
  208.       wsprintf((LPSTR)szFilterLine[CALLWNDPROCINDEX],
  209.            "CALLWNDPROC\tWnd:%d\t%s %s                    ",
  210.            lptsParamStruct->hwnd,
  211.            szMessageString(lptsParamStruct->message), (LPSTR)szType);
  212.  
  213.       hDC = GetDC(hwndMain);
  214.       TabbedTextOut(hDC, 1, nLineHeight * CALLWNDPROCINDEX,
  215.         (LPSTR)szFilterLine[CALLWNDPROCINDEX],
  216.         strlen(szFilterLine[CALLWNDPROCINDEX]), 0, NULL, 1);
  217.       ReleaseDC(hwndMain, hDC);
  218.  
  219.    }
  220.  
  221.    //
  222.    // We looked at the message ... sort of processed it but since we are
  223.    // looking we will pass all messages on to CallNextHookEx.
  224.    //
  225.    CallNextHookEx(hhookHooks[CALLWNDPROCINDEX], nCode, (WORD)wParam,(WORD) lParam);
  226.    return;
  227. }
  228.  
  229. //---------------------------------------------------------------------------
  230. // CbtFunc
  231. //
  232. // Filter function for the WH_CBT
  233. //
  234. //---------------------------------------------------------------------------
  235. int FAR PASCAL CbtFunc (int nCode, WORD wParam, DWORD lParam )
  236. {
  237.    HDC           hDC;
  238.    CBTACTIVATESTRUCT FAR *Active;
  239.    LPMOUSEHOOKSTRUCT MouseHookParam;
  240.    LPCBT_CREATEWND   CreateWndParam;
  241.    LPRECT         Rect;
  242.  
  243.    if ( nCode >= 0 ) {
  244.       switch ( nCode ) {
  245.       case HCBT_ACTIVATE:
  246.          Active = (CBTACTIVATESTRUCT FAR *) lParam;
  247.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  248.           "CBT\t\tGoing to Activate Wnd:%d Wnd:%d is active. Mouse Flag:%d                      ",
  249.           wParam,Active->hWndActive,Active->fMouse);
  250.  
  251.          break;
  252.  
  253.       case HCBT_CLICKSKIPPED:
  254.          MouseHookParam = (LPMOUSEHOOKSTRUCT) lParam;
  255.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  256.           "CBT\t\tMouse Message Removed from Queue. Point:%d %d %s                              ",
  257.           MouseHookParam->pt.x,MouseHookParam->pt.y,
  258.           szMessageString(wParam));
  259.  
  260.          break;
  261.  
  262.       case HCBT_CREATEWND:
  263.          CreateWndParam = (LPCBT_CREATEWND) lParam;
  264.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  265.                   "CBT\t\tGoing to Create Wnd:%d %s %s                                                  ",
  266.                   wParam,CreateWndParam->lpcs->lpszName,CreateWndParam->lpcs->lpszClass);
  267.          break;
  268.  
  269.       case HCBT_DESTROYWND:
  270.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  271.           "CBT\t\tGoing to Destroy Wnd:%d                                                       ",
  272.           wParam);
  273.  
  274.          break;
  275.  
  276.       case HCBT_KEYSKIPPED:
  277.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  278.           "CBT\t\tKeyboard Message Removed from Queue. Key:%d                                   ",
  279.           wParam);
  280.  
  281.          break;
  282.  
  283.       case HCBT_MINMAX:
  284.          switch ( LOWORD(lParam) ) {
  285.          case SW_HIDE:
  286.             _fstrcpy(szType, "SW_HIDE");
  287.             break;
  288.  
  289.          case SW_NORMAL:
  290.             _fstrcpy(szType, "SW_NORMAL");
  291.             break;
  292.  
  293.          case SW_SHOWMINIMIZED:
  294.             _fstrcpy(szType, "SW_SHOWMINIMIZED");
  295.             break;
  296.  
  297.          case SW_MAXIMIZE:
  298.             _fstrcpy(szType, "SW_MAXIMIZE");
  299.             break;
  300.  
  301.          case SW_SHOWNOACTIVATE:
  302.             _fstrcpy(szType, "SW_SHOWNOACTIVATE");
  303.             break;
  304.  
  305.          case SW_SHOW:
  306.             _fstrcpy(szType, "SW_SHOW");
  307.             break;
  308.  
  309.          case SW_MINIMIZE:
  310.             _fstrcpy(szType, "SW_MINIMIZE");
  311.             break;
  312.  
  313.          case SW_SHOWMINNOACTIVE:
  314.             _fstrcpy(szType, "SW_SHOWMINNOACTIVE");
  315.             break;
  316.  
  317.          case SW_SHOWNA:
  318.             _fstrcpy(szType, "SW_SHOWNA");
  319.             break;
  320.  
  321.          case SW_RESTORE:
  322.             _fstrcpy(szType, "SW_RESTORE");
  323.             break;
  324.  
  325.          default:
  326.             _fstrcpy(szType,"Unknown Message");
  327.  
  328.          }
  329.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  330.           "CBT\t\tGoing to MIN/MAX Wnd:%d %s                                                    ",
  331.           wParam,(LPSTR)szType);
  332.  
  333.          break;
  334.  
  335.       case HCBT_MOVESIZE:
  336.          Rect = (LPRECT) lParam;
  337.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  338.           "CBT\t\tGoing to MOVE/SIZE Wnd:%d to %d %d %d %d                                      ",
  339.           wParam,Rect->left,Rect->top,Rect->right,Rect->bottom);
  340.  
  341.          break;
  342.  
  343.       case HCBT_QS:
  344.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  345.           "CBT\t\tWM_QUEUESYNC Message                                                          ");
  346.  
  347.          break;
  348.  
  349.       case HCBT_SETFOCUS:
  350.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  351.           "CBT\t\tGiving Focus to Wnd:%d Taking Focus From Wnd:%d                               ",
  352.           wParam,LOWORD(lParam));
  353.  
  354.          break;
  355.  
  356.       case HCBT_SYSCOMMAND:
  357.          switch ( wParam ) {
  358.           case SC_SIZE:
  359.              _fstrcpy(szType,"SC_SIZE");
  360.              break;
  361.  
  362.           case SC_MOVE:
  363.              _fstrcpy(szType,"SC_MOVE");
  364.              break;
  365.  
  366.           case SC_MINIMIZE:
  367.              _fstrcpy(szType,"SC_MINIMIZE");
  368.              break;
  369.  
  370.           case SC_MAXIMIZE:
  371.              _fstrcpy(szType,"SC_MAXIMIZE");
  372.              break;
  373.  
  374.           case SC_NEXTWINDOW:
  375.              _fstrcpy(szType,"SC_NEXTWINDOW");
  376.              break;
  377.  
  378.           case SC_PREVWINDOW:
  379.              _fstrcpy(szType,"SC_PREVWINDOW");
  380.              break;
  381.  
  382.           case SC_CLOSE:
  383.              _fstrcpy(szType,"SC_CLOSE");
  384.              break;
  385.  
  386.           case SC_VSCROLL:
  387.              _fstrcpy(szType,"SC_VSCROLL");
  388.              break;
  389.  
  390.           case SC_HSCROLL:
  391.              _fstrcpy(szType,"SC_HSCROLL");
  392.              break;
  393.  
  394.           case SC_MOUSEMENU:
  395.              _fstrcpy(szType,"SC_MOUSEMENU");
  396.              break;
  397.  
  398.           case SC_KEYMENU:
  399.              _fstrcpy(szType,"SC_KEYMENU");
  400.              break;
  401.  
  402.           case SC_ARRANGE:
  403.              _fstrcpy(szType,"SC_ARRANGE");
  404.              break;
  405.  
  406.           case SC_RESTORE:
  407.              _fstrcpy(szType,"SC_RESTORE");
  408.              break;
  409.  
  410.           case SC_TASKLIST:
  411.              _fstrcpy(szType,"SC_TASKLIST");
  412.              break;
  413.  
  414.           case SC_SCREENSAVE:
  415.              _fstrcpy(szType,"SC_SCREENSAVE");
  416.              break;
  417.  
  418.           case SC_HOTKEY:
  419.              _fstrcpy(szType,"SC_HOTKEY");
  420.              break;
  421.  
  422.          default:
  423.             _fstrcpy(szType,"Unknown Message");
  424.  
  425.          }
  426.          wsprintf((LPSTR)szFilterLine[CBTINDEX],
  427.           "CBT\t\tAbout to Perform System Command: %s                                           ",
  428.           (LPSTR)szType);
  429.  
  430.          break;
  431.  
  432.       }
  433.  
  434.       hDC = GetDC(hwndMain);
  435.       TabbedTextOut(hDC, 1, nLineHeight * CBTINDEX,
  436.         (LPSTR)szFilterLine[CBTINDEX],
  437.         strlen(szFilterLine[CBTINDEX]), 0, NULL, 1);
  438.       ReleaseDC(hwndMain, hDC);
  439.    }
  440.  
  441.    //
  442.    // We looked at the message ... sort of processed it but since we are
  443.    // looking we will pass all messages on to CallNextHookEx.
  444.    //
  445.    return( (int)CallNextHookEx(hhookHooks[CBTINDEX], nCode,(WORD)wParam,(WORD) lParam));
  446. }
  447.  
  448. //---------------------------------------------------------------------------
  449. // GetMessageFunc
  450. //
  451. // Filter function for the WH_GETMESSAGE
  452. //
  453. //---------------------------------------------------------------------------
  454. void FAR PASCAL GetMessageFunc (int nCode, WORD wParam, DWORD lParam )
  455. {
  456.    MSG FAR *lpMsg;
  457.    HDC       hDC;
  458.  
  459.    if ( nCode >= 0 ) {
  460.       lpMsg = (MSG FAR *) lParam;
  461.       wsprintf((LPSTR)szFilterLine[GETMESSAGEINDEX],
  462.            "GETMESSAGE\tWnd:%d Time:%ld  Point:%d %d %s                                  ",
  463.            lpMsg->hwnd, lpMsg->time,
  464.            lpMsg->pt.x, lpMsg->pt.y, szMessageString(lpMsg->message));
  465.  
  466.  
  467.       hDC = GetDC(hwndMain);
  468.       TabbedTextOut(hDC, 1, nLineHeight * GETMESSAGEINDEX,
  469.         (LPSTR)szFilterLine[GETMESSAGEINDEX],
  470.         strlen(szFilterLine[GETMESSAGEINDEX]), 0, NULL, 1);
  471.       ReleaseDC(hwndMain, hDC);
  472.    }
  473.  
  474.    //
  475.    // We looked at the message ... sort of processed it but since we are
  476.    // looking we will pass all messages on to CallNextHookEx.
  477.    //
  478.    CallNextHookEx(hhookHooks[GETMESSAGEINDEX], nCode, wParam, lParam);
  479.    return;
  480. }
  481.  
  482. //---------------------------------------------------------------------------
  483. // JournalPlaybackFunc
  484. //
  485. // Filter function for the WH_JOURNALPLAYBACK
  486. //
  487. //---------------------------------------------------------------------------
  488. DWORD FAR PASCAL JournalPlaybackFunc (int nCode, WORD wParam, DWORD lParam )
  489. {
  490.    HDC         hDC;
  491.    static int     nRepeatRequests;
  492.    HANDLE     hEvent;
  493.    LPEVENTMSG lpEvent;
  494.    static DWORD  dwTimeAdjust;
  495.    long      lReturnValue;
  496.    static DWORD  dwLastEventTime;
  497.    HMENU     hMenu;
  498.  
  499.    if ( nCode >= 0 ) {
  500.       // No Playback if we haven't recorded an Event
  501.       //
  502.       // No Playback While recording.
  503.       // This is not a limitation of the hooks.
  504.       // This is only because of the simple event storage used in this example
  505.       //
  506.       // We should never get here since the enable / disable menu stuff should
  507.       // make getting here impossible
  508.       //
  509.       if ( lpEventChain == NULL || HookStates[JOURNALRECORDINDEX]) {
  510.       InstallFilter(JOURNALPLAYBACKINDEX, FALSE);
  511.       hMenu = GetMenu(hwndMain);
  512.       CheckMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_UNCHECKED | MF_BYCOMMAND);
  513.       EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
  514.       wsprintf((LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  515.           "WH_JOURNALPLAYBACK -- No recorded Events to Playback  or JournalRecord in Progress                  ");
  516.       hDC = GetDC(hwndMain);
  517.       TabbedTextOut(hDC, 1, nLineHeight * JOURNALPLAYBACKINDEX,
  518.         (LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  519.         strlen(szFilterLine[JOURNALPLAYBACKINDEX]), 0, NULL, 1);
  520.       ReleaseDC(hwndMain, hDC);
  521.           return( (int)CallNextHookEx(hhookHooks[JOURNALPLAYBACKINDEX], nCode, wParam, lParam ));
  522.       }
  523.  
  524.       if ( lpPlayEvent == NULL ) {
  525.      lpPlayEvent = lpEventChain;
  526.      lpLastEvent = NULL;       // For the next time we start the recorder
  527.      dwTimeAdjust = GetTickCount() - dwStartRecordTime;
  528.      dwLastEventTime = (DWORD) GetTickCount();
  529.      nRepeatRequests = 1;
  530.       }
  531.  
  532.       if (nCode == HC_SKIP ) {
  533.       nRepeatRequests = 1;
  534.  
  535.       if ( lpPlayEvent->lpNextEvent == NULL ) {
  536.           wsprintf((LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  537.               "WH_JOURNALPLAYBACK -- Done Recorded Events");
  538.           hDC = GetDC(hwndMain);
  539.           TabbedTextOut(hDC, 1, nLineHeight * JOURNALPLAYBACKINDEX,
  540.             (LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  541.             strlen(szFilterLine[JOURNALPLAYBACKINDEX]), 0, NULL, 1);
  542.           ReleaseDC(hwndMain, hDC);
  543.  
  544.           hEvent = (HANDLE)LOWORD(GlobalHandle((HIWORD(lpEventChain))));
  545.           GlobalUnlock(hEvent);
  546.           GlobalFree(hEvent);
  547.           lpEventChain = lpPlayEvent = NULL ;
  548.  
  549.           InstallFilter(JOURNALPLAYBACKINDEX, FALSE);
  550.           hMenu = GetMenu(hwndMain);
  551.           CheckMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_UNCHECKED | MF_BYCOMMAND);
  552.           EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
  553.       }
  554.       else {
  555.           dwLastEventTime = lpPlayEvent->Event.time;
  556.           lpPlayEvent = lpPlayEvent->lpNextEvent;
  557.  
  558.           hEvent = (HANDLE)LOWORD(GlobalHandle((HIWORD(lpEventChain))));
  559.           GlobalUnlock(hEvent);
  560.           GlobalFree(hEvent);
  561.           lpEventChain = lpPlayEvent;
  562.       }
  563.       }
  564.       else if ( nCode == HC_GETNEXT) {
  565.       lpEvent = (LPEVENTMSG) lParam;
  566.       lpEvent->message = lpPlayEvent->Event.message;
  567.       lpEvent->paramL  = lpPlayEvent->Event.paramL;
  568.       lpEvent->paramH  = lpPlayEvent->Event.paramH;
  569.       lpEvent->time    = lpPlayEvent->Event.time + dwTimeAdjust;
  570.  
  571.       wsprintf((LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  572.            "WH_JOURNALPLAYBACK -- Playing Event %d times                    ",
  573.            nRepeatRequests++);
  574.       hDC = GetDC(hwndMain);
  575.       TabbedTextOut(hDC, 1, nLineHeight * JOURNALPLAYBACKINDEX,
  576.         (LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  577.         strlen(szFilterLine[JOURNALPLAYBACKINDEX]), 0, NULL, 1);
  578.       ReleaseDC(hwndMain, hDC);
  579.  
  580.       lReturnValue = lpEvent->time - GetTickCount();
  581.       //
  582.       // No Long ( negative ) waits
  583.       //
  584.       if ( lReturnValue < 0L ) {
  585.          lReturnValue  = 0L;
  586.          lpEvent->time = GetTickCount();
  587.       }
  588.       return ( (DWORD) lReturnValue );
  589.       }
  590.  
  591.       hDC = GetDC(hwndMain);
  592.       TabbedTextOut(hDC, 1, nLineHeight * JOURNALPLAYBACKINDEX,
  593.         (LPSTR)szFilterLine[JOURNALPLAYBACKINDEX],
  594.         strlen(szFilterLine[JOURNALPLAYBACKINDEX]), 0, NULL, 1);
  595.       ReleaseDC(hwndMain, hDC);
  596.    }
  597.  
  598.    return( (int)CallNextHookEx(hhookHooks[JOURNALPLAYBACKINDEX], nCode, wParam, lParam));
  599. }
  600.  
  601. //---------------------------------------------------------------------------
  602. // JournalRecordFunc
  603. //
  604. // Filter function for the WH_JOURNALRECORD
  605. //
  606. //---------------------------------------------------------------------------
  607. void FAR PASCAL JournalRecordFunc (int nCode, WORD wParam, DWORD lParam )
  608. {
  609.    HDC       hDC;
  610.    HANDLE      hEvent;
  611.    EventNode FAR *lpEventNode;
  612.    LPEVENTMSG  lpEvent;
  613.    HMENU      hMenu;
  614.  
  615.    if ( nCode >= 0 ) {
  616.  
  617.       lpEvent = (LPEVENTMSG) lParam;
  618.       //
  619.       // Skip recording while playing back
  620.       // This is not a limitation of the hooks.
  621.       // This is only because of the simple event storage used in this example
  622.       //
  623.       if ( HookStates[JOURNALPLAYBACKINDEX] ) {
  624.      wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  625.            "WH_JOURNALRECORD\tSkipping Recording during Playback                        ");
  626.      hDC = GetDC(hwndMain);
  627.      TabbedTextOut(hDC, 1, nLineHeight * JOURNALRECORDINDEX,
  628.            (LPSTR)szFilterLine[JOURNALRECORDINDEX],
  629.            strlen(szFilterLine[JOURNALRECORDINDEX]), 0, NULL, 1);
  630.      ReleaseDC(hwndMain, hDC);
  631.      return;
  632.       }
  633.  
  634.       //
  635.       // Stop recording ?
  636.       //
  637.       if ( lpEvent->message == WM_KEYDOWN &&
  638.        LOBYTE(lpEvent->paramL)  == VK_F2 ) {
  639.      wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  640.            "WH_JOURNALRECORD\tRecording Stopped with F2                                                                 ");
  641.      InstallFilter(JOURNALRECORDINDEX, FALSE);
  642.      hMenu = GetMenu(hwndMain);
  643.      CheckMenuItem(hMenu, IDM_JOURNALRECORD, MF_UNCHECKED | MF_BYCOMMAND);
  644.      EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_ENABLED | MF_BYCOMMAND);
  645.      return ;
  646.       }
  647.  
  648.       if ((hEvent=
  649.       GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,sizeof(EventNode))) == NULL ) {
  650.      wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  651.            "WH_JOURNALRECORD\tNo Memory Available");
  652.      InstallFilter(JOURNALRECORDINDEX, FALSE);
  653.      hMenu = GetMenu(hwndMain);
  654.      CheckMenuItem(hMenu, IDM_JOURNALRECORD, MF_UNCHECKED | MF_BYCOMMAND);
  655.      EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_ENABLED | MF_BYCOMMAND);
  656.      return;
  657.       }
  658.       if ( (lpEventNode = (EventNode FAR *)GlobalLock(hEvent)) == NULL ) {
  659.      GlobalFree(hEvent);
  660.      wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  661.            "WH_JOURNALRECORD\tNo Memory Available");
  662.      InstallFilter(JOURNALRECORDINDEX, FALSE);
  663.      hMenu = GetMenu(hwndMain);
  664.      CheckMenuItem(hMenu, IDM_JOURNALRECORD, MF_UNCHECKED | MF_BYCOMMAND);
  665.      EnableMenuItem(hMenu, IDM_JOURNALPLAYBACK, MF_ENABLED | MF_BYCOMMAND);
  666.       }
  667.  
  668.  
  669.       if ( lpLastEvent == NULL ) {
  670.      dwStartRecordTime = (DWORD) GetTickCount();
  671.      lpEventChain = lpEventNode;
  672.       }
  673.       else {
  674.      lpLastEvent->lpNextEvent = lpEventNode;
  675.       }
  676.  
  677.       lpLastEvent = lpEventNode;
  678.       lpLastEvent->lpNextEvent = NULL;
  679.  
  680.       lpLastEvent->Event.message = lpEvent->message;
  681.       lpLastEvent->Event.paramL  = lpEvent->paramL;
  682.       lpLastEvent->Event.paramH  = lpEvent->paramH;
  683.       lpLastEvent->Event.time     = lpEvent->time;
  684.  
  685.  
  686.       wsprintf((LPSTR)szFilterLine[JOURNALRECORDINDEX],
  687.         "WH_JOURNALRECORD\tRecording\tTime:%ld\tPRESS F2 To Stop Recording\t%s                        ",
  688.         lpEvent->time,szMessageString(lpEvent->message));
  689.       hDC = GetDC(hwndMain);
  690.       TabbedTextOut(hDC, 1, nLineHeight * JOURNALRECORDINDEX,
  691.         (LPSTR)szFilterLine[JOURNALRECORDINDEX],
  692.         strlen(szFilterLine[JOURNALRECORDINDEX]), 0, NULL, 1);
  693.       ReleaseDC(hwndMain, hDC);
  694.       return;
  695.    }
  696.  
  697.    CallNextHookEx(hhookHooks[JOURNALRECORDINDEX], nCode, wParam, lParam);
  698.    return;
  699. }
  700.  
  701. //---------------------------------------------------------------------------
  702. // KeyboardFunc
  703. //
  704. // Filter function for the WH_KEYBOARD
  705. //
  706. //---------------------------------------------------------------------------
  707. int FAR PASCAL KeyboardFunc (int nCode, WORD wParam, DWORD lParam )
  708. {
  709.    HDC           hDC;
  710.  
  711.    if ( nCode >= 0 ) {
  712.  
  713.       if ( nCode == HC_NOREMOVE )
  714.      _fstrcpy(szType, "NOT Removed from Queue");
  715.       else
  716.      _fstrcpy(szType, "REMOVED from Queue                                             ");
  717.  
  718.       wsprintf((LPSTR)szFilterLine[KEYBOARDINDEX],
  719.            "KEYBOARD\tKey:%d\t%s",wParam,(LPSTR)szType);
  720.  
  721.       hDC = GetDC(hwndMain);
  722.       TabbedTextOut(hDC, 1, nLineHeight * KEYBOARDINDEX,
  723.         (LPSTR)szFilterLine[KEYBOARDINDEX],
  724.         strlen(szFilterLine[KEYBOARDINDEX]), 0, NULL, 1);
  725.       ReleaseDC(hwndMain, hDC);
  726.    }
  727.  
  728.    //
  729.    // We looked at the message ... sort of processed it but since we are
  730.    // looking we will pass all messages on to CallNextHookEx.
  731.    //
  732.    return( (int)CallNextHookEx(hhookHooks[KEYBOARDINDEX], nCode, wParam, lParam));
  733. }
  734.  
  735. //---------------------------------------------------------------------------
  736. // MouseFunc
  737. //
  738. // Filter function for the WH_MOUSE
  739. //
  740. //---------------------------------------------------------------------------
  741. int FAR PASCAL MouseFunc (int nCode, WORD wParam, DWORD lParam )
  742. {
  743.    HDC           hDC;
  744.    LPMOUSEHOOKSTRUCT MouseHookParam;
  745.  
  746.    if ( nCode >= 0 ) {
  747.       if ( nCode == HC_NOREMOVE )
  748.      _fstrcpy(szType, "NOT Removed from Queue");
  749.       else
  750.      _fstrcpy(szType, "REMOVED from Queue                                             ");
  751.  
  752.       MouseHookParam = (MOUSEHOOKSTRUCT FAR *) lParam;
  753.  
  754.       wsprintf((LPSTR)szFilterLine[MOUSEINDEX],
  755.           "MOUSE\t\tWnd:%d Point:%d %d\t%s %s",MouseHookParam->hwnd,
  756.           MouseHookParam->pt.x,MouseHookParam->pt.y,
  757.           szMessageString(wParam),(LPSTR)szType);
  758.  
  759.       hDC = GetDC(hwndMain);
  760.       TabbedTextOut(hDC, 1, nLineHeight * MOUSEINDEX,
  761.         (LPSTR)szFilterLine[MOUSEINDEX], strlen(szFilterLine[MOUSEINDEX]),
  762.         0, NULL, 1 );
  763.       ReleaseDC(hwndMain, hDC);
  764.  
  765.    }
  766.  
  767.    //
  768.    // We looked at the message ... sort of processed it but since we are
  769.    // looking we will pass all messages on to CallNextHookEx.
  770.    //
  771.    return( (int)CallNextHookEx(hhookHooks[MOUSEINDEX], nCode, wParam, lParam));
  772. }
  773.  
  774. //---------------------------------------------------------------------------
  775. // SysMsgFilterFunc
  776. //
  777. // Filter function for the WH_SYSMSGFILTER
  778. //
  779. //---------------------------------------------------------------------------
  780. int FAR PASCAL SysMsgFilterFunc (int nCode, WORD wParam, DWORD lParam )
  781. {
  782.    MSG FAR *lpMsg;
  783.    HDC           hDC;
  784.  
  785.    if ( nCode >= 0 ) {
  786.       if ( nCode == MSGF_DIALOGBOX )
  787.      _fstrcpy(szType,"Dialog");
  788.       else
  789.      _fstrcpy(szType,"Menu");
  790.  
  791.       lpMsg = (MSG FAR *) lParam;
  792.       wsprintf((LPSTR)szFilterLine[SYSMSGFILTERINDEX],
  793.            "SYSMSGFILTER\t%s\tWnd:%d Time:%ld  Point:%d %d %s                                ",
  794.            (LPSTR)szType, lpMsg->hwnd, lpMsg->time,
  795.            lpMsg->pt.x, lpMsg->pt.y, szMessageString(lpMsg->message));
  796.  
  797.       hDC = GetDC(hwndMain);
  798.       TabbedTextOut(hDC, 1, nLineHeight * SYSMSGFILTERINDEX,
  799.         (LPSTR)szFilterLine[SYSMSGFILTERINDEX],
  800.         strlen(szFilterLine[SYSMSGFILTERINDEX]), 0, NULL, 1 );
  801.       ReleaseDC(hwndMain, hDC);
  802.    }
  803.  
  804.    //
  805.    // We looked at the message ... sort of processed it but since we are
  806.    // looking we will pass all messages on to CallNextHookEx.
  807.    //
  808.    return( (int)CallNextHookEx(hhookHooks[SYSMSGFILTERINDEX], nCode, wParam, lParam));
  809. }
  810.  
  811.  
  812. //---------------------------------------------------------------------------
  813. // MessageString
  814. //
  815. // Function to load string from the STRINGTABLE
  816. //
  817. //---------------------------------------------------------------------------
  818. char FAR * szMessageString(WORD wID)
  819. {
  820.    static char szBuffer[256];
  821.  
  822.    if ( LoadString(hInstance, wID, szBuffer, 255) == 0)
  823.       _fstrcpy(szBuffer,"Unknown Message");
  824.  
  825.    return (szBuffer);
  826.  
  827. }
  828.